package templatepattern

import "fmt"

// DownLoader template method
type DownLoader interface {
	Download(uri string)
}

// abstract method
type implement interface {
	download()
	save()
}

type template struct {
	implement
	uri string
}

// Download here, we specify the template download process
func (t *template) Download(uri string) {
	t.uri = uri
	fmt.Println("prepare to download")
	t.implement.download()
	t.implement.save()
	fmt.Println("done")
}

func (t *template) save() {
	fmt.Println("default save")
}

func newTemplate(impl implement) *template {
	return &template{
		implement: impl,
		uri:       "",
	}
}

type HttpDownloader struct {
	*template
}

func (hd *HttpDownloader) download() {
	fmt.Printf("download %v via HTTP\n", hd.uri)
}

func (hd *HttpDownloader) save() {
	fmt.Println("HTTP save")
}

func NewHttpDownloader() *HttpDownloader {
	downloader := &HttpDownloader{}
	template := newTemplate(downloader)
	downloader.template = template
	return downloader
}

type FtpDownloader struct {
	*template
}

func (hd *FtpDownloader) download() {
	fmt.Printf("download %v via FTP\n", hd.uri)
}

func (hd *FtpDownloader) save() {
	fmt.Println("FTP save")
}

func NewFtpDownloader() *FtpDownloader {
	downloader := &FtpDownloader{}
	template := newTemplate(downloader)
	downloader.template = template
	return downloader
}
